﻿using System;
using System.Xml;
using System.Xml.Linq;
using Castle.Core.Configuration;
using Castle.Core.Resource;
using Castle.MicroKernel;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using Mistral.Configuration;
using Mistral.Serialization;
using Mistral.Xml;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Spring.Context.Support;
using Spring.Core.IO;
using Spring.Objects.Factory.Xml;
using IResource=Castle.Core.Resource.IResource;

namespace Mistral.Tests
{
	[TestFixture]
	public class SerializationTests
	{
		readonly string _sampleComponentXml = "<SampleComponent Message='Hello' />";

		[Test]
		public void LoadObjectFromXml()
		{

			IObjectLoader objectLoader = new DefaultObjectLoader();
			objectLoader.RegisterTypeAlias( "SampleComponent", typeof(SampleComponent) );
			IObjectDefinition objectDefinition = objectLoader.LoadFromXml( _sampleComponentXml );

			Assert.IsNotNull( objectDefinition, "objectDefinition" );
			Assert.That( objectDefinition.PropertyValues.Count, Is.EqualTo(1), "PropertyValues.Count" );
			Assert.That( objectDefinition.Type, Is.EqualTo( "SampleComponent" ), "objectDefinition.Type" );

			PropertyValue propertyValue = objectDefinition.PropertyValues.GetProperty( "Message" );
			Assert.IsNotNull( propertyValue, "propertyValue" );
			Assert.That( propertyValue.Value, Is.EqualTo("Hello"), "Property value" );

//			CastleAdapter adapter = new CastleAdapter();
//			IConfiguration configuration = adapter.Convert( objectDefinition );
//			IConfigurationStore configurationStore = new DefaultConfigurationStore();
//			configurationStore.AddComponentConfiguration( "a", configuration );
//			WindsorContainer container = new WindsorContainer( configurationStore );
//			object service = container.Resolve( "a" );
//			Assert.IsNotNull( service );
		}

		[Test]
		public void TestWindsor()
		{
			string text = "<configuration><components><component id='a' type='Mistral.Tests.SampleComponent, Mistral.Tests'><parameters><Message>Hello</Message></parameters></component></components></configuration>";
			object service = GetCastleService( text, "a" );
			Assert.IsNotNull( service );
		}



		[Test]
		public void TestDefaultParser()
		{
			XmlDocument document = new XmlDocument();
			document.LoadXml( _sampleComponentXml );

			DefaultParser parser = new DefaultParser( typeof(SampleComponent) );
			Spring.Objects.Factory.Config.IObjectDefinition definition = parser.ParseElement( document.DocumentElement, null );
			GenericApplicationContext context = new GenericApplicationContext();
			context.RegisterObjectDefinition( "a", definition );
			object service = context.GetObject( "a" );
			Assert.IsNotNull( service );
		}

       
		[Test]
		public void TestCastleSerializer()
		{
			CastleObjectSerializer serializer = new CastleObjectSerializer();
			string text = serializer.ComponentToElement( new SampleComponent {Message = "Hello"}, "a" ).ToString();
			Console.WriteLine(text);

			ColumnCustomizer columnCustomizer = new ColumnCustomizer();
//			columnCustomizer.ColumnInfos = new[]
//						   {
//							   new ColumnInfo{ PropertyName = "Code"        , Order = 1 },
//							   new ColumnInfo{ PropertyName = "Name"        , Order = 2 },
//						   };
			XElement configurationElement = new XElement( "configuration" );
			XElement componentsElement = new XElement( "components" );
			configurationElement.Add( componentsElement );
			componentsElement.Add( serializer.ComponentToElement( columnCustomizer, "customizer" ) );
			text = configurationElement.ToString();
			Console.WriteLine(text);

			object service = GetCastleService( text, "customizer" );
			Assert.IsNotNull( service );
		}

		[Test]
		public void TestSpringSerializer()
		{
			var serializer = new SpringObjectSerializer();

			ColumnCustomizer columnCustomizer = new ColumnCustomizer();
			columnCustomizer.ColumnInfos = new[]
						   {
							   new ColumnInfo{ PropertyName = "Code"        , Order = 1 },
							   new ColumnInfo{ PropertyName = "Name"        , Order = 2 },
						   };
			XElement configurationElement = new XElement( XName.Get( "objects", "http://www.springframework.net" ) );
			XElement objectElement = serializer.ComponentToElement( columnCustomizer, "customizer" );
			configurationElement.Add( objectElement );
			string text = configurationElement.ToString();
			Console.WriteLine(text);

			object service = GetSpringService( text, "customizer" );
			Assert.IsNotNull( service );
		}


		private object GetCastleService( string text, string serviceName )
		{
			IResource resource = new StaticContentResource( text );
			var interpreter = new XmlInterpreter(resource);
			WindsorContainer container = new WindsorContainer( interpreter );
			return container.Resolve( serviceName );
		}

		private object GetSpringService( string text, string serviceName )
		{
			Spring.Core.IO.IResource resource = new StringResource( text );
			XmlObjectFactory factory = new XmlObjectFactory( resource );
			return factory.GetObject( serviceName );
		}
	}

	[RegisterAlias("SampleComponent")]
	public class SampleComponent
	{
		[Serialization.Property(NodeType = NodeType.XmlAttribute)]
		public string Message { get; set; }
	}

	/// <summary>
	/// Переопределение информации о столбцах.
	/// </summary>
	interface IColumnCustomizer
	{
		/// <summary>
		/// Информация о столбцах.
		/// </summary>
		ColumnInfo[] ColumnInfos{ get; }
	}

	class ColumnInfo
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="T:System.Object"/> class.
		/// </summary>
		public ColumnInfo( )
		{
			Visible = true;
			Order = int.MaxValue;
		}

		/// <summary>
		/// Имя свойства.
		/// </summary>
		public string PropertyName{ get; set; }

		/// <summary>
		/// Отображаемое имя.
		/// </summary>
		public string DisplayName{ get; set; }

		/// <summary>
		/// Показать/Скрыть столбец.
		/// </summary>
		public bool Visible{ get; set; }

		/// <summary>
		/// Порядок следования.
		/// </summary>
		public int Order{ get; set; }
	}

	class ColumnCustomizer : IColumnCustomizer
	{
		/// <summary>
		/// Информация о столбцах.
		/// </summary>
		public ColumnInfo[] ColumnInfos{ get; set; }
	}

	class ColumnCustomizer_OrgUnit : IColumnCustomizer
	{
		#region Implementation of IColumnCustomizer

		/// <summary>
		/// Информация о столбцах.
		/// </summary>
		public ColumnInfo[] ColumnInfos
		{
			get
			{
				return new[]
						   {
							   new ColumnInfo{ PropertyName = "OrgUnitID"    , Order = 1 },
							   new ColumnInfo{ PropertyName = "Code"        , Order = 2 },
							   new ColumnInfo{ PropertyName = "Name"        , Order = 3 },
							   new ColumnInfo{ PropertyName = "Type"        , Order = 4 },
							   new ColumnInfo{ PropertyName = "Description", Order = 5 },
							   new ColumnInfo{ PropertyName = "IsEnable"    , Order = 6 },
						   };
			}
		}

		#endregion
	}
}

